﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using System.IO;
using WindowsForms_Logic_Questions_Generator.Operators;


namespace WindowsForms_Logic_Questions_Generator
{
    public partial class Form1 : Form
    {
        private ListQestions Questions;
        private DocumentParser m_DocumentParser;
        private DocumentExtraData m_DocExtraData;
        DataGridViewCellEventArgs mouseLocation;
                       
        public Form1()
        {
            InitializeComponent();            
            dateTimePicker.CustomFormat = "ddd dd MMM yyyy";
            
            Questions = new ListQestions();
            Questions.Clear();

            m_DocExtraData = new DocumentExtraData();
            m_DocExtraData.SetStudentNameData(textBoxStudentName.Text);
            m_DocExtraData.SetHeaderData(textBoxHeader.Text);
            m_DocExtraData.SetDateData(dateTimePicker.Value.ToShortDateString());
            m_DocExtraData.SetExplanationData(textBoxExplanation.Text);
            m_DocExtraData.SetFinalExplanationData(textBoxFinalExplanation.Text);
            m_DocExtraData.SetGoodLuckData(textBoxGoodLuck.Text);
            
            m_DocumentParser = new DocumentParser(m_DocExtraData);
            textBoxTest.ScrollBars = ScrollBars.Vertical;
            // Add menu
            AddContextMenu(dataGridViewTestData);
            // remember mouse location
            AddMouseEnterEvent();

            UnVisibleAll(true);            
        }

        private void Form1_Load(object sender, EventArgs e)
        {
             
        }

        private void saveTestToolStripMenuItem_Click(object sender, EventArgs e)
        {
            bool bGenerate = false;
            string message = "";
            string caption = "";
            var result = DialogResult.None;

            if (! textBoxTest.Visible)
            {
                message = "Nothing to Save/Print\nCanceling this operation";
                caption = "cancellation";
                result = MessageBox.Show(message, caption,
                                             MessageBoxButtons.OK,
                                             MessageBoxIcon.Information);

                return;
            }

            message = "Would you like also generate printable exams?";
            caption = "Question";
            result = MessageBox.Show(message, caption,
                                         MessageBoxButtons.YesNo,
                                         MessageBoxIcon.Question);

            // If the Yes button was pressed ...
            if (result == DialogResult.Yes)
            {
                bGenerate = true;
            }
            m_DocumentParser.SaveTest(Questions, bGenerate);
        }

        private void loadTestToolStripMenuItem_Click(object sender, EventArgs e)
        {
            var result = DialogResult.Cancel;

            if (textBoxTest.Visible)
            {
                const string message = "Are you sure that you would like to load existing test over this one without saving it?\n\nYes: Clear existing qustions in bank.\nNo: Add questions to existing qustions in bank";
                const string caption = "Attention";
                result = MessageBox.Show(message, caption,
                                             MessageBoxButtons.YesNoCancel,
                                             MessageBoxIcon.Error);

                // If the cancle button was pressed ...
                if (result == DialogResult.Cancel)
                {
                    // cancel this operation.
                    return;
                }

                if (result == DialogResult.Yes)
                {
                    UnVisibleAll(true);
                }
            }
            
            
            if (m_DocumentParser.LoadTest(Questions))
            {
                mathTestCreator();

                //Fill the Math Test data;
                textBoxStudentName.Text = m_DocExtraData.GetStudentNameData();
                textBoxHeader.Text = m_DocExtraData.GetHeaderData();
                dateTimePicker.Text = m_DocExtraData.GetDateData();
                textBoxExplanation.Text = m_DocExtraData.GetExplanationData();
                textBoxFinalExplanation.Text = m_DocExtraData.GetFinalExplanationData();
                textBoxGoodLuck.Text = m_DocExtraData.GetGoodLuckData();
                //TODO:: Fill Questions Queue.
                int nHowMany = Questions.HowMany();
                if (0 < nHowMany)
                {
                    dataGridViewTestData.Visible = true;
                    textBoxTest.Clear();
                    dataGridViewTestData.ClearSelection();
                    while (0 < dataGridViewTestData.Rows.Count)
                    {
                        if (dataGridViewTestData.Rows[0].IsNewRow == false)
                            dataGridViewTestData.Rows.RemoveAt(0);
                    }
                    for (int index = 0; index < nHowMany; index++)
                    {
                        int n = dataGridViewTestData.Rows.Add();
                        dataGridViewTestData.Rows[n].Cells[0].Value = Questions.ToStringAt(index);
                    }
                    dataGridViewTestData.ClearSelection();
                }
            }           
        }

        private void mathTestCreator()
        {
            textBoxTest.Visible = true;
            buttonPlus.Visible = true;
            buttonMinus.Visible = true;
            buttonMul.Visible = true;
            buttonDiv.Visible = true;
            buttonEqual.Visible = true;
            buttonRange.Visible = true;
            buttonClearQuestion.Visible = true;
            buttonClearComment.Visible = true;
            buttoComment.Visible = true;
            buttoComment.Visible = true;
            textBoxFrom.Visible = true;
            textBoxTo.Visible = true;
            textBoxComment.Visible = true;
            //buttoAddQuestionToQuiz.Visible = true;
            textBoxStudentName.Visible = true;
            textBoxHeader.Visible = true;
            dateTimePicker.Visible = true;
            textBoxExplanation.Visible = true;
            labelTextTest.Visible = true;
            textBoxFinalExplanation.Visible = true;
            textBoxGoodLuck.Visible = true;
            textBoxStudentName.Text = "Student Name: _______________";
            textBoxHeader.Text = "Math Exam";
            dateTimePicker.Value = DateTime.Today;
            textBoxExplanation.Text = "General explanation about the entire test (total time of the test, general intructions, etc... ) : ";
            textBoxFinalExplanation.Text = "Final explanation about the entire test  ('check before handing out the exam', etc...) : ";
            textBoxComment.Text = "for example: 'Choose 5 out of 8 of the following questions'";
            textBoxGoodLuck.Text = "Good luck!";
        }

        private void UnVisibleAll(bool bclearData)
        {
            textBoxTest.Visible = false;            
            buttonPlus.Visible = false;
            buttonMinus.Visible = false;
            buttonMul.Visible = false;
            buttonDiv.Visible = false;
            buttonEqual.Visible = false;
            buttonRange.Visible = false;
            buttonClearQuestion.Visible = false;
            buttonClearComment.Visible = false;
            buttoComment.Visible = false;
            buttonRange.Enabled = false;
            buttoComment.Enabled = false;
            buttonRange.SendToBack();
            buttoComment.SendToBack();
            textBoxFrom.Visible = false;            
            textBoxFrom.BringToFront();
            textBoxTo.Visible = false;            
            textBoxTo.BringToFront();
            textBoxComment.Visible = false;            
            textBoxComment.BringToFront();
            buttoAddQuestionToQuiz.Visible = false;
            dataGridViewTestData.Visible = false;
            textBoxStudentName.Visible = false;
            textBoxHeader.Visible = false;
            dateTimePicker.Visible = false;
            textBoxExplanation.Visible = false;
            labelTextTest.Visible = false;
            textBoxFinalExplanation.Visible = false;
            textBoxGoodLuck.Visible = false;
            textBoxTest.Clear();
            textBoxFrom.Clear();
            textBoxTo.Clear();
            textBoxComment.Clear();
            if (bclearData)
            {
                Questions.Clear();
                while (0 < dataGridViewTestData.Rows.Count)
                {
                    if (dataGridViewTestData.Rows[0].IsNewRow == false)
                        dataGridViewTestData.Rows.RemoveAt(0);
                }
            }
        }



        private void AppendTextToTextBoxTest(string strOpperand)
        {
            if (textBoxTest.SelectionStart == 0) textBoxTest.Text = textBoxTest.Text.Insert(textBoxTest.SelectionLength, strOpperand);
            else textBoxTest.SelectedText = strOpperand;
            textBoxTest.Focus();
           
        }

        private void AppendTextToTextBoxComment(string strOpperand)
        {
            if (textBoxComment.SelectionStart == 0) textBoxComment.Text = textBoxComment.Text.Insert(textBoxComment.SelectionLength, strOpperand);
            else textBoxComment.SelectedText = strOpperand;
            textBoxComment.Focus();

        }
        
        private void buttonPlus_Click(object sender, EventArgs e)
        {
            Operators.PlusButton p = new Operators.PlusButton();
            AppendTextToTextBoxTest(p.ToString()); //"{+}"
        }

        private void buttonMinus_Click(object sender, EventArgs e)
        {
            Operators.MinusButton p = new Operators.MinusButton();
            AppendTextToTextBoxTest(p.ToString()); //"{-}"
        }

        private void buttonMul_Click(object sender, EventArgs e)
        {
            Operators.MulButton p = new Operators.MulButton();
            AppendTextToTextBoxTest(p.ToString()); //"{*}"
        }

        private void buttonDiv_Click(object sender, EventArgs e)
        {
            Operators.DivButton p = new Operators.DivButton();
            AppendTextToTextBoxTest(p.ToString()); //"{/}"
        }

        private void buttonEqual_Click(object sender, EventArgs e)
        {
            Operators.EqualButton p = new Operators.EqualButton();
            AppendTextToTextBoxTest(p.ToString()); //"{=}"
            //textBoxTest.AppendText(p.ToString());            

        }

        private void buttonRange_Click(object sender, EventArgs e)
        {
            Operators.RangeButton p = new Operators.RangeButton(textBoxFrom.Text, textBoxTo.Text);
            AppendTextToTextBoxTest(p.ToString()); //"{" + name + ":" + textBoxFrom.Text + ".." + textBoxTo.Text + "}"
            buttonRange.Enabled = false;
            textBoxFrom.Clear();
            textBoxFrom.BringToFront();
            textBoxTo.Clear();
            textBoxTo.BringToFront();
        }
        private void textBoxTo_KeyDown(object sender, KeyEventArgs e)
        {
            CheckNumbersValid(sender, e);            
        }

        private void textBoxFrom_KeyDown(object sender, KeyEventArgs e)
        {
            CheckNumbersValid(sender, e);
        }

        private void CheckNumbersValid(object sender, KeyEventArgs e)
        {
            //Allow navigation keyboard arrows
            switch (e.KeyCode)
            {
                case Keys.Up:
                case Keys.Down:
                case Keys.Left:
                case Keys.Right:
                case Keys.PageUp:
                case Keys.PageDown:
                    e.SuppressKeyPress = false;
                    return;
                default:
                    break;
            }

            //Block non-number characters
            char currentKey = (char)e.KeyCode;
            bool modifier = e.Control || e.Alt || e.Shift;
            bool nonNumber = char.IsLetter(currentKey) ||
                             char.IsSymbol(currentKey) ||
                             char.IsWhiteSpace(currentKey) ||
                             char.IsPunctuation(currentKey);

            if (!modifier && nonNumber)
                e.SuppressKeyPress = true;

            //Handle pasted Text
            if (e.Control && e.KeyCode == Keys.V)
            {
                //Preview paste data (removing non-number characters)
                string pasteText = Clipboard.GetText();
                string strippedText = "";
                for (int i = 0; i < pasteText.Length; i++)
                {
                    if (char.IsDigit(pasteText[i]))
                        strippedText += pasteText[i].ToString();
                }

                if (strippedText != pasteText)
                {
                    //There were non-numbers in the pasted text
                    e.SuppressKeyPress = true;

                    //OPTIONAL: Manually insert text stripped of non-numbers
                    TextBox me = (TextBox)sender;
                    int start = me.SelectionStart;
                    string newTxt = me.Text;
                    newTxt = newTxt.Remove(me.SelectionStart, me.SelectionLength); //remove highlighted text
                    newTxt = newTxt.Insert(me.SelectionStart, strippedText); //paste
                    me.Text = newTxt;
                    me.SelectionStart = start + strippedText.Length;
                }
                else
                    e.SuppressKeyPress = false;
            }
        }

        private void textBoxTo_KeyUp(object sender, KeyEventArgs e)
        {
            buttonRange.Enabled = ((0 != textBoxTo.Text.Length) && (0 != textBoxFrom.Text.Length));
        }

        private void textBoxFrom_KeyUp(object sender, KeyEventArgs e)
        {
            buttonRange.Enabled = ((0 != textBoxTo.Text.Length) && (0 != textBoxFrom.Text.Length));
        }

        private void buttoAddQuestionToQuiz_Click(object sender, EventArgs e)
        {
            Int32 RowToBEditing = dataGridViewTestData.Rows.GetFirstRow(DataGridViewElementStates.Selected);


            ListDataInt qst = new ListDataInt(textBoxTest.Text);
      
            if (RowToBEditing >= 0 ) 
            {
                Questions.RemoveIndex(RowToBEditing);
                Questions.InsertAt(RowToBEditing, qst);
                int index = Questions.IndexOf(qst);
                dataGridViewTestData.Rows[RowToBEditing].Cells[0].Value = Questions.ToStringAt(index);
            }
            else
            {
                int n = dataGridViewTestData.Rows.Add();
                Questions.Add(qst);
                int index = Questions.IndexOf(qst);
                dataGridViewTestData.Rows[n].Cells[0].Value = Questions.ToStringAt(index);
            }
            dataGridViewTestData.Visible = true;
            textBoxTest.Clear();
            dataGridViewTestData.ClearSelection();         

        }

        private void textBoxTest_TextChanged(object sender, EventArgs e)
        {
                buttoAddQuestionToQuiz.Visible = (textBoxTest.TextLength != 0);
        }

        private void createTestToolStripMenuItem_Click(object sender, EventArgs e)
        {
            var result = DialogResult.Cancel;

            if (textBoxTest.Visible)
            {
                const string message = "Are you sure that you would like to clear existing test?";
                const string caption = "Attention";
                result = MessageBox.Show(message, caption,
                                             MessageBoxButtons.YesNo,
                                             MessageBoxIcon.Error);

                // If the No button was pressed ...
                if (result == DialogResult.No)
                {
                    // cancel this operation.
                    return;
                }
            }
            UnVisibleAll(true);
            mathTestCreator();
        }

        private void dataGridViewTestData_MouseClick(object sender, MouseEventArgs e)
        {
            // Load context menu on right mouse click
            DataGridView.HitTestInfo hitTestInfo; 
            if (e.Button == MouseButtons.Right)
            {
                ContextMenu m = new ContextMenu();
                m.MenuItems.Add(new MenuItem("DeleteRow"));
                m.MenuItems.Add(new MenuItem("EditRow"));
                m.MenuItems.Add(new MenuItem("DuplicateRow"));
                
                int currentMouseOverRow = dataGridViewTestData.HitTest(e.X, e.Y).RowIndex;
                hitTestInfo = dataGridViewTestData.HitTest(e.X, e.Y);
                dataGridViewTestData.ClearSelection();
                dataGridViewTestData.Rows[hitTestInfo.RowIndex].Selected = true;               
            }
            else if (e.Button == MouseButtons.Left)
            {
                int currentMouseOverRow = dataGridViewTestData.HitTest(e.X, e.Y).RowIndex;
                hitTestInfo = dataGridViewTestData.HitTest(e.X, e.Y);
                dataGridViewTestData.ClearSelection();
                dataGridViewTestData.Rows[hitTestInfo.RowIndex].Selected = false;
            }
        }


        private void AddContextMenu(DataGridView dgv)
        {
            var strip = new ContextMenuStrip();
            var DeleteRow = strip.Items.Add("DeleteRow");
            var EditRow = strip.Items.Add("EditRow");
            var DuplicateRow = strip.Items.Add("DuplicateRow");
            DuplicateRow.Click += new EventHandler(DuplicateRow_Click);
            DeleteRow.Click += new EventHandler(DeleteRow_Click);
            EditRow.Click += new EventHandler(EditRow_Click);

            foreach (DataGridViewColumn column in dgv.Columns)
                column.ContextMenuStrip = strip;
        }

        void AddMouseEnterEvent()
        {
            dataGridViewTestData.CellMouseEnter += (s, e) => { mouseLocation = e; };           
        }

        void EditRow_Click(object sender, EventArgs e)
        {
            textBoxTest.Clear();
            Int32 rowToEdit =  mouseLocation.RowIndex;
            string stringToEdit = Questions.ToStringAt(rowToEdit);
            if (stringToEdit[1] != '#') AppendTextToTextBoxTest(stringToEdit);
            else {
                string CmtToEdit = stringToEdit.Substring(15);
                AppendTextToTextBoxComment(CmtToEdit);
            } 
            dataGridViewTestData.ClearSelection();
            dataGridViewTestData.Rows[rowToEdit].Selected = true;
            
        }

        void DeleteRow_Click(object sender, EventArgs e)
        {
            Int32 rowToDelete = mouseLocation.RowIndex;
            Questions.RemoveIndex(rowToDelete);
            dataGridViewTestData.Rows.RemoveAt(rowToDelete);
            dataGridViewTestData.ClearSelection();
        }

        void DuplicateRow_Click(object sender, EventArgs e)
        {
            Int32 rowToDuplicate = mouseLocation.RowIndex;
            Questions.InsertAt(rowToDuplicate, Questions.ElementAt(rowToDuplicate));
            dataGridViewTestData.Rows.Insert(rowToDuplicate,Questions.ToStringAt(rowToDuplicate));
            dataGridViewTestData.ClearSelection();
        }

        private void textBoxComment_TextChanged(object sender, EventArgs e)
        {
            buttoComment.Enabled = (textBoxComment.TextLength != 0);
        }

       
        private void buttoComment_Click(object sender, EventArgs e)
        {
            ListDataInt qst = new ListDataInt();
            qst.Add(new FreeData("#comment:# :  " + textBoxComment.Text));
            Int32 RowToBEditing = dataGridViewTestData.Rows.GetFirstRow(DataGridViewElementStates.Selected);

            if (RowToBEditing >= 0)
            {
                Questions.RemoveIndex(RowToBEditing);
                Questions.InsertAt(RowToBEditing, qst);
                int index = Questions.IndexOf(qst);
                dataGridViewTestData.Rows[RowToBEditing].Cells[0].Value = Questions.ToStringAt(index);
            }
            else
            {
                int n = dataGridViewTestData.Rows.Add();
                Questions.Add(qst);
                int index = Questions.IndexOf(qst);
                dataGridViewTestData.Rows[n].Cells[0].Value = Questions.ToStringAt(index);
            }

            dataGridViewTestData.ClearSelection();

            dataGridViewTestData.Visible = true;
            buttoComment.Enabled = false;
            textBoxComment.Clear();
            textBoxComment.BringToFront();
            dataGridViewTestData.ClearSelection();
        }

        private void dataGridViewTestData_CellContentClick(object sender, DataGridViewCellEventArgs e)
        {

        }
        
        private void textBoxStudentName_Leave(object sender, EventArgs e)
        {
            m_DocExtraData.SetStudentNameData(textBoxStudentName.Text);
        }

        private void textBoxHeader_Leave(object sender, EventArgs e)
        {
            m_DocExtraData.SetHeaderData(textBoxHeader.Text);
        }

        private void dateTimePicker_Leave(object sender, EventArgs e)
        {
            m_DocExtraData.SetDateData(dateTimePicker.Value.ToShortDateString());
        }

        private void dateTimePicker_Leave(object sender, DragEventArgs e)
        {
            m_DocExtraData.SetDateData(dateTimePicker.Value.ToShortDateString());
        }

        private void textBoxExplanation_Leave(object sender, EventArgs e)
        {
            m_DocExtraData.SetExplanationData(textBoxExplanation.Text);
        }

        private void textBoxFinalExplanation_Leave(object sender, EventArgs e)
        {
            m_DocExtraData.SetFinalExplanationData(textBoxFinalExplanation.Text);
        }

        private void textBoxGoodLuck_Leave(object sender, EventArgs e)
        {
            m_DocExtraData.SetGoodLuckData(textBoxGoodLuck.Text);
        }

        private void textBoxFrom_TextChanged(object sender, EventArgs e)
        {

        }

        private void buttonClearQuestion_Click(object sender, EventArgs e)
        {
            textBoxTest.Clear();
        }
      

        private void buttonClearComment_Click_1(object sender, EventArgs e)
        {
            textBoxComment.Clear();
        }

        private void labelTextTest_Click(object sender, EventArgs e)
        {

        }

        private void openRTFFileToolStripMenuItem_Click(object sender, EventArgs e)
        {
            System.Windows.Forms.OpenFileDialog openRTFDialog = new System.Windows.Forms.OpenFileDialog();
            openRTFDialog.DefaultExt = "rtf";
            openRTFDialog.FileName = "openFileDialog1";
            openRTFDialog.Filter = "RTF Files|*.rtf";
            DialogResult res = openRTFDialog.ShowDialog();
            if (res == DialogResult.OK)
            {
                Form x = new Form3();
                ((Form3)x).openFileToolStripMenuItem_Click(openRTFDialog.FileName);
                x.ShowDialog();
            }
            
        }       
    }
    
}
